package com.aiyige.utils;

import android.annotation.TargetApi;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Canvas;
import android.graphics.NinePatch;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.media.ThumbnailUtils;
import android.os.Build;
import android.os.Environment;
import android.provider.MediaStore.Images.Thumbnails;
import android.util.DisplayMetrics;
import android.util.Log;

import com.aiyige.configs.MyConfig;
import com.aiyige.page.my.localVideo.IOUtils;
import com.vondear.rxtools.RxFileTool;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.ByteBuffer;

public class BitmapUtils {
	private static final String TAG = BitmapUtils.class.getSimpleName();
	public static final int UNCONSTRAINED = -1;

	public static Bitmap clip(Bitmap bm, float ratio) {
		if (bm == null) {
			return null;
		}
		if (bm.isRecycled()) {
			return null;
		}
		if (ratio <= 0) {
			throw new IllegalArgumentException("clip ratio must>0");
		}
		int srcWidth = bm.getWidth();
		int srcHeight = bm.getHeight();
		int dstWidth;
		int dstHeight;
		if (srcHeight * ratio < srcWidth) {
			dstWidth = (int) Math.ceil(ratio * srcHeight);
			dstHeight = srcHeight;
		} else if (srcWidth / ratio < srcHeight) {
			dstHeight = (int) Math.ceil(srcWidth / ratio);
			dstWidth = srcWidth;
		} else {
			dstWidth = srcWidth;
			dstHeight = srcHeight;
		}
		Rect src = new Rect();
		src.left = (srcWidth - dstWidth) / 2;
		src.right = src.left + dstWidth;
		src.top = (srcHeight - dstHeight) / 2;
		src.bottom = src.top + dstHeight;
		Rect dst = new Rect(0, 0, dstWidth, dstHeight);
		Bitmap result = Bitmap.createBitmap(dstWidth, dstHeight,
				Config.RGB_565);
		Canvas canvas = new Canvas(result);
		canvas.drawBitmap(bm, src, dst, null);
		bm.recycle();

		return result;
	}
	
	public static Bitmap makeBitmap(int minSideLength, int maxNumOfPixels,
			String pathName) {
		try {
			Options options=new Options();
			options.inJustDecodeBounds = true;
			BitmapFactory.decodeFile(pathName, options);
			if (options.mCancel || options.outWidth == -1
					|| options.outHeight == -1) {
				return null;
			}
			options.inSampleSize = computeSampleSize(options, minSideLength,
					maxNumOfPixels);
			options.inJustDecodeBounds = false;
			options.inDither = false;
			options.inPurgeable=true;
			options.inPreferredConfig = Config.RGB_565;
			try {
				options.inDensity = DisplayMetrics.class.getDeclaredField(
						"DENSITY_DEVICE").getInt(null);
			} catch (Exception e) {
				options.inDensity = DisplayMetrics.DENSITY_DEFAULT;
			}
			try {
				Options.class.getDeclaredField("inNativeAlloc").setBoolean(
						options, true);
			} catch (Exception e) {
			}
			return BitmapFactory.decodeFile(pathName, options);
		} catch (OutOfMemoryError ex) {
			System.gc();
			System.runFinalization();
			return null;
		}
	}


	public static Bitmap makeBitmap(int minSideLength, int maxNumOfPixels,
			byte[] data) {
		try {
			Options options=new Options();
			options.inJustDecodeBounds = true;
			BitmapFactory.decodeByteArray(data, 0, data.length, options);
			if (options.mCancel || options.outWidth == -1
					|| options.outHeight == -1) {
				return null;
			}
			options.inSampleSize = computeSampleSize(options, minSideLength,
					maxNumOfPixels);
			options.inJustDecodeBounds = false;
			options.inDither = false;
			options.inPurgeable=true;
			options.inPreferredConfig = Config.RGB_565;
			try {
				options.inDensity = DisplayMetrics.class.getDeclaredField(
						"DENSITY_DEVICE").getInt(null);
			} catch (Exception e) {
				options.inDensity = DisplayMetrics.DENSITY_DEFAULT;
			}
			try {
				Options.class.getDeclaredField("inNativeAlloc").setBoolean(
						options, true);
			} catch (Exception e) {
			}
			return BitmapFactory.decodeByteArray(data, 0, data.length, options);
		} catch (OutOfMemoryError ex) {
			return null;
		}
	}
	public static int computeSampleSize(Options options,
			int minSideLength, int maxNumOfPixels) {
		int initialSize = computeInitialSampleSize(options, minSideLength,
				maxNumOfPixels);
		int roundedSize;
		if (initialSize <= 8) {
			roundedSize = 1;
			while (roundedSize < initialSize) {
				roundedSize <<= 1;
			}
		} else {
			roundedSize = (initialSize + 7) / 8 * 8;
		}
		return roundedSize;
	}

	private static int computeInitialSampleSize(Options options,
			int minSideLength, int maxNumOfPixels) {
		double w = options.outWidth;
		double h = options.outHeight;
		int lowerBound = (maxNumOfPixels == UNCONSTRAINED) ? 1 : (int) Math
				.ceil(Math.sqrt(w * h / maxNumOfPixels));
		int upperBound = (minSideLength == UNCONSTRAINED) ? 128 : (int) Math
				.min(Math.floor(w / minSideLength),
						Math.floor(h / minSideLength));

		if (upperBound < lowerBound) {
			return lowerBound;
		}

		if ((maxNumOfPixels == UNCONSTRAINED)
				&& (minSideLength == UNCONSTRAINED)) {
			return 1;
		} else if (minSideLength == UNCONSTRAINED) {
			return lowerBound;
		} else {
			return upperBound;
		}
	}

	
	public static String saveBitmap(Bitmap bitmap, String filePath) {
		FileOutputStream fos = null;
		try {
			File file = new File(filePath);
//			if (!file.exists()) {
//				file.createNewFile();
//			}
			fos = new FileOutputStream(file);
			if (null != fos) {
				bitmap.compress(Bitmap.CompressFormat.PNG, 90, fos);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return null;
		} finally {
			IOUtils.closeSilently(fos);
		}

		return filePath;
	}

	
	/**
	 * 获取视频第一帧的缩略图
	 * @param path
	 * @return
	 */
	public static String createVideoThumbnail(String path) {
		File dir = new File(Environment.getExternalStorageDirectory()
				+ MyConfig.AIYIGE_COVER_DIR);
		if (!dir.exists()) {
			dir.mkdir();
		}
		String url = null;
		try {
			String fileName = MD5Utils.getMD5String(path) + ".jpg";
			File tempFile = new File(dir.getPath(), fileName);
			if (tempFile.exists()) {
				return tempFile.getPath();
			}
			Bitmap videoThumb = ThumbnailUtils.createVideoThumbnail(path,
					Thumbnails.MINI_KIND);
			
			if (null != videoThumb) {
				url = saveBitmap(videoThumb, tempFile.getPath());
			}
			videoThumb.recycle();
		} catch (Exception e) {
			Log.e("BitmapUtils", e.toString());
			url = null;
		} catch (OutOfMemoryError e) {
			Log.e("BitmapUtils", e.toString());
			System.gc();
			System.runFinalization();
			url = null;
		} 
		
		return url;
	}

	
	@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
	public static byte[] convertBitmapToBytes(Bitmap bitmap) {
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
			ByteBuffer buffer = ByteBuffer.allocate(bitmap.getByteCount());
			bitmap.copyPixelsToBuffer(buffer);
			return buffer.array();
		} else {
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
			byte[] data = baos.toByteArray();
			return data;
		}
	}
	
	public static void downloadImage(String urlStr, String path) {
		Log.d("--wk--", "downloadImage url : " + urlStr + "  path : " + path);
		InputStream is = null;
		FileOutputStream fos = null;
		try {
			File file = new File(path);
			URL url = new URL(urlStr);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setConnectTimeout(5000);
			conn.setRequestMethod("GET");
			conn.setDoInput(true);
			if (conn.getResponseCode() == 200) {
				 is = conn.getInputStream();
				 fos = new FileOutputStream(file);
				byte[] buffer = new byte[1024];
				int len;
				while ((len = is.read(buffer)) != -1) {
					fos.write(buffer, 0, len);
				}

			}
		} catch (Exception e) {
			e.printStackTrace();
			RxFileTool.deleteFile(path);
		}finally {
			IOUtils.closeSilently(is);
			IOUtils.closeSilently(fos);
		}

	}

	public static Bitmap getRoundCornerImage(Bitmap bitmap_bg, Bitmap bitmap_in, int imgW, int imgH) {
		Bitmap roundConcerImage = Bitmap.createBitmap(imgW, imgH, Config.RGB_565);
		Canvas canvas = new Canvas(roundConcerImage);
		Paint paint = new Paint();
		Rect rect = new Rect(0, 0, imgW, imgH);
		Rect rectF = new Rect(0, 0, bitmap_in.getWidth(), bitmap_in.getHeight());
		paint.setAntiAlias(true);
		NinePatch patch = new NinePatch(bitmap_bg, bitmap_bg.getNinePatchChunk(), null);
		patch.draw(canvas, rect);
		paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
		canvas.drawBitmap(bitmap_in, rectF, rect, paint);
		return roundConcerImage;
	}

}
